package my.util.monitor;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

public abstract class DiskFileMonitor implements FileMonitor{

	private final String ServiceFilesKey = "ServiceFiles";
	private final String ServiceFilesMapKey = "ServiceFilesMapKey";
	private String filePath = "./src/cn/std/pool/cache";
	
	public DiskFileMonitor(String fpath) {
		try {
			filePath  = fpath;
			Vector<String> files = new Vector<String>();
			getFiles(files, fpath);
			CacheMgr.putCache(ServiceFilesKey,files);
			Map<String,String> hm = new HashMap<String,String>(files.size());
			for(String f:files){
				String fp = fpath+"/"+f;
				fp = fp.replaceAll("//", "/");
				try {
					String hash = HashFile.getHash(fp, "MD5");
					hm.put(f, hash);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			CacheMgr.putCache(ServiceFilesMapKey, hm);
			CacheMgr.lsCache();
			//Vector ve = (Vector)CacheMgr.getCache(ServiceFilesKey);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/** 递归获取目录下的所有文件 */
	private static void getFiles(Vector<String> ret,String fpath) throws IOException { 
        File dir = new File(fpath); 
        File[] files = dir.listFiles(); 
        
        if (files == null) 
            return; 
        for (int i = 0; i < files.length; i++) { 
            if (files[i].isDirectory()) { 
            	getFiles(ret,files[i].getAbsolutePath()); 
            } else { 
                String fileName = files[i].getName();
                ret.addElement(fileName);
            } 
        } 
    }
	
	@SuppressWarnings("unchecked")
	public void run() {
		try {
			Vector<String> notLoadFiles = new Vector<String>();
			while(true){
				Vector<String> diskfiles = new Vector<String>();
				getFiles(diskfiles, filePath);//从磁盘中读出文件
				//判断文件是否已经加载
				Object obj = CacheMgr.getCache(ServiceFilesKey);
				Vector<String> cachefiles = null;
				if(obj instanceof Vector){
					cachefiles = (Vector<String>)obj;
				}
				if(null != cachefiles){
					int diskfilesSize = diskfiles.size();
					int cachefilesSize = cachefiles.size();
					
					//磁盘文件>缓存文件，说明磁盘中增加了文件
					if(diskfilesSize > cachefilesSize){
						Enumeration<String> diskEn = diskfiles.elements();
						while(diskEn.hasMoreElements()){
							Object diskElement = diskEn.nextElement();
							if(cachefiles.contains(diskElement)){//如果缓存中已经包含了磁盘元素，进行下一个循环
								continue;
							}else{
								notLoadFiles.addElement((String)diskElement);
							}
						}//end while 
					//磁盘中删除了文件
					}else if(diskfilesSize < cachefilesSize){
						Enumeration<String> cacheEn = cachefiles.elements();
						while(cacheEn.hasMoreElements()){
							Object cacheElement = cacheEn.nextElement();
							if(diskfiles.contains(cacheElement)){//如果缓存中已经包含了磁盘元素，进行下一个循环
								continue;
							}else{
								cachefiles.removeElement(cacheElement);
							//	System.out.println(cacheElement+" 文件删除");
								deleteAction(cacheElement);
								HashMap<String,String> upmap = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);
								upmap.remove(cacheElement);
							}
						}//end while 
					//文件数量没有变化,分两种情况，1，删除N个文件同时又增加了N个文件。2，文件原封不动
					}else {
						Map<String,String> hm = (Map<String, String>) CacheMgr.getCache(ServiceFilesMapKey);
						Enumeration<String> diskEn = diskfiles.elements();
						Vector<Object> isIn = new Vector<Object>(diskfilesSize);
						while(diskEn.hasMoreElements()){
							Object diskElement = diskEn.nextElement();
							String diskfilepath = filePath+"/"+diskElement;
							diskfilepath = diskfilepath.replace("//", "/");
							String newhash = HashFile.getHash(diskfilepath, "MD5");
							String mapHash = hm.get(diskElement);
							if(null != mapHash){//如果不为空，说明有这个文件
								isIn.addElement(diskElement);
								if(mapHash.equals(newhash)){
									continue;
								}else{
									updateAction(diskElement);
									//更新文件hash
									HashMap<String,String> upmap = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);
									upmap.put(diskElement.toString(),newhash);
								}
							}else{//如果为空，说明重命名了一个文件
							//	deleteAction(diskElement);
								addAction(diskElement);
								hm.put(diskElement.toString(), newhash);
								cachefiles.addElement(diskElement.toString());
								isIn.addElement(diskElement);
							} 
						}//end while
						
						List<String> willRemove = new ArrayList<String>(hm.size());
						//遍历已经存在的元素，找出被重命名的元素
						for(Map.Entry<String, String> m:hm.entrySet()){
							if(isIn.contains(m.getKey())){
								continue;
							}else{
								willRemove.add(m.getKey());
							}
						}
						
						for(String element:willRemove){
							hm.remove(element);
							cachefiles.removeElement(element);
							deleteAction(element);
						}
					}
					
					if(notLoadFiles.size() == 0){
						//服务文件没有更新
					}else{
						//服务文件更新
						
						Vector<String> loadedfiles = new Vector<String>();
						//此处加载服务文件
						for(String name:notLoadFiles){
					//		System.out.println(name+" 未加载");
							addAction(name);
					//		System.out.println(name+" 正在加载..");
							loadedfiles.addElement(name);
							isLoading(name);
					//		System.out.println(name+" 加载成功");
							cachefiles.addElement(name);
							HashMap<String, String> hm = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);
							String path = filePath+"/"+name;
							path = path.replace("//", "/");
							hm.put(name,HashFile.getHash(path, "MD5"));
							loadSuccess(name);
							CacheMgr.lsCache();
						}
						notLoadFiles.removeAll(loadedfiles);
					}
				}
				Thread.sleep(500);
			}//end while(true)
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
